home *** CD-ROM | disk | FTP | other *** search
/ MacWorld 1998 March / Macworld (1998-03) (Disk 1).dmg / Shareware World / Info / For Developers / GhostScript 5.10 / MacGS-510 / files / t1tot2.ps < prev    next >
Text File  |  1997-09-20  |  13KB  |  486 lines

  1. %    Copyright (C) 1997 Aladdin Enterprises.  All rights reserved.
  2. % This file is part of Aladdin Ghostscript.
  3. % Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author
  4. % or distributor accepts any responsibility for the consequences of using it,
  5. % or for whether it serves any particular purpose or works at all, unless he
  6. % or she says so in writing.  Refer to the Aladdin Ghostscript Free Public
  7. % License (the "License") for full details.
  8. % Every copy of Aladdin Ghostscript must include a copy of the License,
  9. % normally in a plain ASCII text file named PUBLIC.  The License grants you
  10. % the right to copy, modify and redistribute Aladdin Ghostscript, but only
  11. % under certain conditions described in the License.  Among other things, the
  12. % License requires that the copyright notice and this notice be preserved on
  13. % all copies.
  14.  
  15. % t1tot2.ps
  16. % Convert a Type 1 font with Type 1 CharStrings to Type 2.
  17. % **************** THIS FILE DOES NOT WORK. ****************
  18. % **************** DON'T TRY TO USE IT. ****************
  19.  
  20. (type1ops.ps) runlibfile
  21.  
  22. % ---------------- CharString conversion ---------------- %
  23.  
  24. % In the following lists, implemented conversions are marked with a +.
  25. % The following conversions are required for each CharString:
  26. % +    Remove lenIV initial bytes and decrypt.
  27. % +    Move width to first stem/moveto.
  28. % +    Move all hstem/vstem commands to the beginning,
  29. %      including any from subroutines.
  30. %    Fold side bearing into first moveto.
  31. % +    Adjust Subr indices for bias.
  32. % +    Remove all closepath.
  33. %    Convert Flex othersubrs to new flex commands.
  34. %    Convert hint replacement to -hm and hintmask.
  35. %    Convert MM blend othersubrs to new blend command.
  36. %    For seac, convert char bodies to subrs, add hint replacement.
  37. % +    Make width relative to nominalWidthX, or omit if equal to
  38. %      defaultWidthX.
  39. % The following patterns allow shortening CharStrings:
  40. % +    rlineto+ => rlineto
  41. % +    rlineto+ (hlineto | vlineto) rlineto+ => rlineto
  42. % +    vlineto (hlineto vlineto)* [hlineto] => vlineto
  43. % +    hlineto (vlineto hlineto)* [vlineto] => hlineto
  44. % +    rrcurveto+ => rrcurveto
  45. % +    rrcurveto+ rlineto => rcurveline
  46. % +    rlineto+ rrcurveto => rlinecurve
  47. % +    (vhcurveto hvcurveto)* [vhcurveto ["hrcurveto"] | "vrcurveto"] =>
  48. %      vhcurveto
  49. % +    (hvcurveto vhcurveto)* [hvcurveto ["vrcurveto"] | "hrcurveto"] =>
  50. %      hvcurveto
  51. %    "rvcurveto" (0 y1 x2 y2 0 y3 rrcurveto)* => vvcurveto
  52. %    "hrcurveto" (x1 0 x2 y2 x3 0 rrcurveto)* => hhcurveto
  53.  
  54. % Convert a CharString from Type 1 to Type 2.
  55. % Free variables: font, subrmap.
  56.  
  57. /t1tot2cs {        % <charstring1> <forsubr> t1tot2cs <charstring2>
  58.   10 dict begin
  59.   /forsubr exch def
  60.     % Collect the hints, side bearing, and width.
  61.   /vhints 10 dict def
  62.   /hhints 10 dict def
  63.   /hmcount null def
  64.   /lsb null def
  65.   /width null def
  66.   forsubr not {
  67.     dup t1hintops t1scan pop
  68.   } if
  69.   t1t2ops t1scan
  70.   [
  71.   forsubr not {
  72.     % Insert the hints and width at the beginning.
  73.     width dup font /nominalWidthX .knownget { sub } if
  74.     exch font /defaultWidthX .knownget not { 0 } if
  75.     eq { pop } if
  76.     /hstem hhints hintlist
  77.     /vstem vhints hintlist
  78.   } if
  79.   counttomark 2 add -1 roll aload pop ]
  80.     % Convert the string back to encoded form.
  81.   DEBUG {
  82.     (++++ ) print [ 1 index { dup null eq { pop } if } forall ] == flush
  83.   } if
  84.   /lenIV 0 def        % for charproc_string
  85.   charproc_string end
  86. } bind def
  87. /hintlist {        % <hintop> <dict> hintlist -
  88.   dup length 0 eq {
  89.     pop pop
  90.   } {
  91.     dup length array dup 3 -1 roll {
  92.       exch put dup
  93.     } forall pop
  94.     % ****** SORT THE HINTS BY INCREASING v ******
  95.     { dup length 24 le { exit } if
  96.       dup 0 24 getinterval { aload pop 4 2 roll } forall
  97.       dup length 24 sub 24 exch getinterval
  98.     } loop
  99.     { aload pop 3 2 roll } forall
  100.   } ifelse
  101. } bind def
  102. /uneexec {        % <string> <lenIV> uneexec <string>
  103.   dup 0 ge {
  104.     2 copy mark /seed 4330 /lenIV 5 -1 roll .dicttomark /eexecDecode filter
  105.             % Stack: string lenIV filter
  106.     dup 4 -1 roll length 4 -1 roll sub string readstring pop
  107.     exch closefile
  108.   } {
  109.     pop
  110.   } ifelse
  111. } bind def
  112. /t1scan {        % <charstring> <opsdict> t1scan <tokens>
  113.   5 dict begin
  114.   /opsdict exch def
  115.     % Remove encryption and convert to symbolic form for processing.
  116.   font /lenIV .knownget not { 4 } if uneexec
  117.   0 () /SubFileDecode filter /f exch def
  118.   /cstr [ 20 { null } repeat f charstack_read /END 20 { null } repeat ] def
  119.   DEBUG {
  120.     (**** ) print [ cstr { dup null eq { pop } if } forall ] == flush
  121.   } if
  122.     % Scan the unpacked string.
  123.   /i 20 def {
  124.     % The /END token will exit from this loop.
  125.     opsdict cstr i get .knownget { exec } if
  126.     /i i 1 add def
  127.   } loop
  128.   f closefile cstr end
  129. } bind def
  130. /ciget {        % <di> ciget <token>
  131.   i add cstr exch get
  132. } bind def
  133. /ciput {        % <di> <token> ciput -
  134.   exch i add exch cstr 3 1 roll put
  135. } bind def
  136. /ciswap {        % <di> <dj> ciswap -
  137.   2 copy exch ciget exch ciget 3 1 roll ciput ciput
  138. } bind def
  139. /ciskip {        % <di> ciskip -
  140.   i add /i exch def
  141. } bind def
  142.  
  143. % Hint scanning procedures.
  144. /addhint {        % [<v> <dv>] <hintdict> addhint -
  145.   dup 2 index known { pop pop } { dup length 3 -1 roll exch put } ifelse
  146. } bind def
  147.  
  148. /t1hintops mark /END { 0 null ciput exit } bind
  149.  
  150. /vstem {
  151.   cstr i 2 sub 2 getinterval vhints addhint
  152. } bind
  153. /hstem {
  154.   cstr i 2 sub 2 getinterval hhints addhint
  155. } bind
  156. /callsubr {
  157.     %**** DOESN'T HANDLE FLEX YET ****
  158.   -1 ciget /pop eq {
  159.     % This must be a <#> 1 3 /callothersubr /pop /callsubr sequence.
  160.     hmcount null eq { /hmcount [ vhints length hhints length ] store } if
  161.     -5 ciget
  162.   } {
  163.     -1 ciget
  164.   } ifelse
  165.   subrmap 1 index .knownget { exch pop } if
  166.   dup null eq { pop } {
  167.     font /Private get /Subrs get exch get
  168.     t1hintops t1scan pop
  169.   } ifelse
  170. } bind
  171. /hsbw {
  172.   /lsb -2 ciget store
  173.   /width -1 ciget store
  174. } bind
  175. /vstem3 {
  176.   [ -6 ciget -5 ciget ] vhints addhint
  177.   [ -4 ciget -3 ciget ] vhints addhint
  178.   [ -2 ciget -1 ciget ] vhints addhint
  179. } bind
  180. /hstem3 {
  181.   [ -6 ciget -5 ciget ] hhints addhint
  182.   [ -4 ciget -3 ciget ] hhints addhint
  183.   [ -2 ciget -1 ciget ] hhints addhint
  184. } bind
  185. /sbw {
  186.     %**** WHAT ABOUT Y? ****
  187.   /lsb -4 ciget store
  188.   /width -2 ciget store
  189. } bind
  190.  
  191. .dicttomark readonly def    % t1hintops
  192.  
  193. % Conversion procedures.
  194. /t1t2ops mark /END { 0 null ciput exit } bind
  195.  
  196. /hstem {
  197.     % We handled the hints separately, drop them here.
  198.   -2 1 0 { null ciput } for
  199. } bind
  200. /vstem 1 index
  201. /rlineto {
  202.   3 ciget /rlineto eq {
  203.     0 null ciput
  204.   } {
  205.     7 ciget /rrcurveto eq {
  206.       0 null ciput
  207.       7 /rlinecurve ciput
  208.     } {
  209.       5 ciget /rlineto eq {
  210.     2 ciget /hlineto eq {
  211.       0 null ciput
  212.       2 0 ciput
  213.     } {
  214.       2 ciget /vlineto eq {
  215.         0 0 ciput
  216.         2 null ciput
  217.       } if
  218.     } ifelse
  219.       } if
  220.     } ifelse
  221.   } ifelse
  222. } bind
  223. /vlineto {
  224.   2 ciget /hlineto eq {
  225.     0 null ciput
  226.     2 4 ciget /vlineto eq { null } { /vlineto } ifelse ciput
  227.   } if
  228. } bind
  229. /hlineto {
  230.   2 ciget /vlineto eq {
  231.     0 null ciput
  232.     2 4 ciget /hlineto eq { null } { /hlineto } ifelse ciput
  233.   } if
  234. } bind
  235. /rrcurveto {
  236.   7 ciget /rrcurveto eq {
  237.     0 null ciput
  238.   } {
  239.     3 ciget /rlineto eq {
  240.       0 null ciput
  241.       3 /rcurveline ciput
  242.     } {
  243.     %**** WRONG IF MULTIPLE RRCURVETO ****
  244.       -6 ciget 0 eq {
  245.     -6 null ciput
  246.     0 /vhcurveto ciput
  247.       } {
  248.     -5 ciget 0 eq {
  249.       -5 null ciput
  250.       -1 -2 ciswap
  251.       0 /hvcurveto ciput
  252.     } if
  253.       } ifelse
  254.     } ifelse
  255.   } ifelse
  256. } bind
  257. /callsubr {
  258.   -1 ciget subrmap 1 index .knownget { exch pop } if
  259.     % If the Subr was deleted because it was empty, delete the call.
  260.   dup null eq {
  261.     0 null ciput
  262.   } {
  263.     % Subtract the subroutineNumberBias.
  264.     107 sub
  265.   } ifelse -1 exch ciput
  266. } bind
  267. /vhcurveto {
  268.   5 ciget /hvcurveto eq {
  269.     0 null ciput
  270.     10 ciget /vhcurveto eq {
  271.       5 null ciput
  272.     } {
  273.       12 ciget /rrcurveto eq 6 ciget 0 eq and {
  274.     5 null ciput
  275.     6 null ciput
  276.     12 /vhcurveto ciput
  277.     12 ciskip
  278.       } {
  279.     5 /vhcurveto ciput
  280.     5 ciskip
  281.       } ifelse
  282.     } ifelse
  283.   } {
  284.     7 ciget /rrcurveto eq {
  285.       1 ciget 0 eq {
  286.     0 null ciput
  287.     1 null ciput
  288.     5 6 ciswap
  289.     7 /vhcurveto ciput
  290.     7 ciskip
  291.       } if
  292.     } if
  293.   } ifelse
  294. } bind
  295. /hvcurveto {
  296.   5 ciget /vhcurveto eq {
  297.     0 null ciput
  298.     10 ciget /hvcurveto eq {
  299.       5 null ciput
  300.     } {
  301.       12 ciget /rrcurveto eq 7 ciget 0 eq and {
  302.     5 null ciput
  303.     7 null ciput
  304.     10 11 ciswap
  305.     12 /hvcurveto ciput
  306.     12 ciskip
  307.       } {
  308.     5 /hvcurveto ciput
  309.     5 ciskip
  310.       } ifelse
  311.     } ifelse
  312.   } {
  313.     7 ciget /rrcurveto eq {
  314.       2 ciget 0 eq {
  315.     0 null ciput
  316.     2 null ciput
  317.     7 /hvcurveto ciput
  318.     7 ciskip
  319.       } if
  320.     } if
  321.   } ifelse
  322. } bind
  323. /closepath {
  324.   0 null ciput
  325. } bind
  326. /hsbw {
  327.     % We handled this separately, drop it.
  328.   -2 1 0 { null ciput } for
  329. } bind
  330. /dotsection {
  331.     %**************** NYI ****************
  332. } bind
  333. /vstem3 {
  334.     % We handled the hints separately, drop them here.
  335.   -6 1 0 { null ciput } for
  336. } bind
  337. /hstem3 1 index
  338. /seac {
  339.     %**************** NYI ****************
  340. } bind
  341. /sbw {
  342.     % We handled this separately, drop it.
  343.   -4 1 0 { null ciput } for
  344. } bind
  345. /callothersubr {
  346.   -1 ciget 3 eq {
  347.     %**** HANDLE HINT REPLACEMENT ****
  348.     -2 ciget 1 eq 1 ciget /pop eq and 2 ciget /callsubr eq and {
  349.       1 -3 ciget ciput
  350.       -3 1 0 { null ciput } for
  351.     } {
  352.       (**************** 3 callothersubr -- invalid call\n) print
  353.       /t1tot2cs cvx /rangecheck signalerror
  354.     } ifelse
  355.   } if
  356. } bind
  357. /pop {
  358.     %**************** NYI ****************
  359. } bind
  360. /setcurrentpoint {
  361.     %**************** NYI ****************
  362. } bind
  363.  
  364. .dicttomark readonly def    % t1t2ops
  365.  
  366. % ---------------- Font conversion ---------------- %
  367.  
  368. % Copy a font, and remove eexec encryption from it.
  369. /decryptfont {            % <font> decryptfont <font'>
  370.     % Copy the font, CharStrings, Private, and Private.Subrs
  371.   dup length dict copy
  372.   dup /CharStrings 2 copy get dup length dict copy put
  373.   dup /Private 2 copy get dup length dict copy
  374.     dup /Subrs 2 copy get dup length array copy put
  375.   put
  376.   dup /lenIV .knownget not { 4 } if
  377.   1 index /CharStrings get
  378.             % Stack: font' lenIV chars'
  379.   dup { 3 index uneexec 2 index 3 1 roll put } forall pop
  380.   1 index /Private get /Subrs get
  381.             % Stack: font' lenIV Subrs'
  382.   0 1 2 index length 1 sub {
  383.     2 copy get dup type /stringtype eq {
  384.             % Stack: font' lenIV Subrs' index subr
  385.       3 index uneexec
  386.     } if 2 index 3 1 roll put
  387.   } for pop pop dup /lenIV -1 put
  388. } def
  389.  
  390. % Convert an entire font from Type 1 to Type 2.
  391. /t1tot2font {            % <font> t1tot2font <font'>
  392.   10 dict begin
  393.   /font exch def
  394.   /niv font /lenIV .knownget not { 4 } if def
  395.  
  396.     % Print initial statistics.
  397.  
  398.   (lenIV = ) print niv =
  399.   font /CharStrings get
  400.   dup length =only ( CharStrings, ) print
  401.   0 exch { exch pop length add } forall =only ( bytes) =
  402.   font /Private get /Subrs get
  403.   dup length =only ( Subrs, ) print
  404.   0 exch { length add } forall =only ( bytes) =
  405.   flush
  406.  
  407.     % Remove CharString encryption from the font.
  408.  
  409.   /font font decryptfont def
  410.   /chars font /CharStrings get dup length dict copy def
  411.   /subrs font /Private get /Subrs get def
  412.  
  413.     % Remove empty Subrs, including Subrs 0-3.
  414.  
  415.   /subrmap subrs length dict def
  416.   0 1 3 { subrs exch <0b> put } for
  417.   0 1 subrs length 1 sub {
  418.     subrs 1 index get true t1tot2cs
  419.     length 1 eq {
  420.       subrs 1 index null put
  421.       subrmap exch null put
  422.     } {
  423.       pop
  424.     } ifelse
  425.   } for
  426.  
  427.     % Remove duplicate Subrs (!).
  428.  
  429.     % Make an entry in subrdict for each distinct Subr:
  430.     %   key = Subr charstring, value = (lowest) Subr index.
  431.     % At the same time, make entries in subrmap for any duplicates:
  432.     %   key = higher index, value = lowest index.
  433.   /subrdict subrs length dict def
  434.   0 0 1 subrs length 1 sub {
  435.         % Stack: toindex fromindex
  436.     subrs 1 index get subrdict 1 index .knownget {
  437.         % Stack: toindex fromindex subr firstindex
  438.       subrmap 4 -1 roll 3 -1 roll put pop
  439.     } {
  440.       dup null ne {
  441.         % Stack: toindex fromindex subr
  442.     subrmap 3 -1 roll 3 index put        % fromindex => toindex
  443.     subrdict 1 index 3 index put        % subr => toindex
  444.     subrs 2 index 3 -1 roll put        % toindex => subr
  445.     1 add
  446.       } {
  447.     pop pop
  448.       } ifelse
  449.     } ifelse
  450.   } for
  451.   /subrs1 subrs 0 4 -1 roll getinterval def
  452.   font /Private get /Subrs subrs1 put
  453.  
  454.     % Convert the font.
  455.  
  456.   /chars2 chars length dict def
  457.   chars { false t1tot2cs chars2 3 1 roll put } forall
  458.   /subrs2 subrs1 length array def
  459.   0 1 subrs1 length 1 sub {
  460.     subrs1 1 index get true t1tot2cs
  461.     subrs2 3 1 roll put
  462.   } for
  463.   font /Private get /Subrs subrs2 put
  464.  
  465.     % Print final statistics.
  466.  
  467.   (CharStrings => ) print 0 chars2 { exch pop length add } forall =only
  468.     ( bytes) =
  469.   subrs2 length =only ( Subrs, ) print
  470.   0 subrs2 { length add } forall =only ( bytes) =
  471.   flush
  472.   
  473.     % Clean up the font.
  474.  
  475.   font /lenIV undef
  476.   font /UniqueID undef
  477.   font /FID undef
  478.   font /CharStrings chars2 put
  479.   font /CharstringType 2 put
  480.  
  481.   font end
  482. } bind def
  483.